package activity

import (
	"context"
	"encoding/json"
	"fmt"
	"sale-admin/internal/app/grpc/protoc/mini_app"
	"sale-admin/internal/dal"
	"strings"
	"time"
	"unicode/utf8"

	"sale-admin/config/mysql"
	"sale-admin/config/redis"
	"sale-admin/internal/app/grpc/client"
	"sale-admin/internal/app/grpc/protoc/system_admin"
	"sale-admin/internal/app/web/schema"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/app/web/service/coupon"
	"sale-admin/internal/app/web/service/redemption"
	"sale-admin/internal/dao"
	"sale-admin/internal/models"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/golang-module/carbon/v2"
	"gorm.io/gorm"
)

type ActivityService struct{}

// List 留资活动列表
func (as ActivityService) List(ctx context.Context, db *gorm.DB, merchantId string, title, id string, Status, page, limit int) (
	ActivityList []models.MaActivity, Count int64, err error,
) {
	tx := db.Model(&models.MaActivity{})
	if strings.TrimSpace(title) != "" {
		tx.Where("title like ?", "%"+strings.TrimSpace(title)+"%")
	}
	if strings.TrimSpace(id) != "" {
		tx.Where("id = ?", strings.TrimSpace(id))
	}
	tx.Where("deleted = 0").Count(&Count)
	ActivityList = []models.MaActivity{}
	helper.Gorm{}.Paginate(tx, page, limit).Order("id desc").Find(&ActivityList)
	return
}

// 活动详情
func (as ActivityService) Detail(ctx context.Context, db *gorm.DB, MerchantID string, ID string) (ActivityInfo *models.MaActivity, err error) {
	ActivityInfo = &models.MaActivity{}
	err = db.Model(&models.MaActivity{}).
		Where("id = ? and deleted = 0", ID).
		Take(ActivityInfo).Error

	if err != nil {
		logx.Error(ctx, "GetMaActivity error", logx.Any("err", err))
		//return
	}

	if ActivityInfo.ID == "" {
		err = errorx.New("活动不存在", -1)
		return nil, err
	}

	return ActivityInfo, nil
}

// Save 保存留资活动
func (as ActivityService) Save(
	ctx context.Context,
	db *gorm.DB,
//MerchantID string,
	item *models.MaActivity,
// ID, couponBatchID, Title, ImagePath, Color, Content string, Status int,
) (err error) {
	if utf8.RuneCountInString(item.Title) >= 10 {
		err = errorx.New("页面标题最多9个字符", -1)
		return
	}

	SystemAdminClient, clientErr := client.GetSystemAdminClient()
	if clientErr != nil {
		err = clientErr
		return
	}

	err = as.VerifyMaActivityParam(item)
	if err != nil {
		logx.Error(ctx, "VerifyMaActivityParam error", logx.Any("item", item), logx.Err(err))
		return err
	}

	if item.CouponBindType == models.CouponBindTypeGoodsClass {
		var GoodsClassCount int64
		db.Model(&models.MaGoodsClass{}).
			Where("class_id = ? and deleted = 0", item.GoodsClassID).
			Count(&GoodsClassCount)
		if GoodsClassCount == 0 {
			err = errorx.New("商品标签不存在", -1)
			return
		}
	} else if item.CouponBindType == models.CouponBindTypeActivity {
		miniAppClient, clientErr := client.GetMiniAppClient()
		if clientErr != nil {
			err = clientErr
			return
		}

		resp, err := miniAppClient.GetOnlineEvent(ctx, &mini_app.GetOnlineEventReq{
			Id: helper.Int64ToString(item.OnlineEventID),
		})

		if err != nil {
			logx.Error(ctx, "GetOnlineEvent error", logx.Any("err", err))
			return errorx.New(fmt.Sprintf("查询活动信息失败: %s", err.Error()), -1)
		}

		if resp.Code != 0 {
			logx.Error(ctx, "GetOnlineEvent error", logx.Any("Msg", resp.Msg))
			return errorx.New(fmt.Sprintf("查询活动信息失败: %s", resp.Msg), -1)
		}

		if resp.Data == nil {
			logx.Error(ctx, "GetOnlineEvent error", logx.Any("err", "活动数据为空"))
			return errorx.New("活动数据为空", -1)
		}

		if resp.Data.Id != helper.Int64ToString(item.OnlineEventID) {
			return errorx.New("活动id不匹配", -1)
		}

	} else if item.CouponBindType == models.CouponBindTypeGoods {
		var filter dao.MaGoodsInfoFilter
		filter.GoodsID = helper.Int64ToString(item.GoodsID)
		rc, err := dao.NewMaGoodsInfoRepo(ctx).FindOneByFilter(ctx, &filter)
		if err != nil || rc == nil {
			return fmt.Errorf("商品不存在：%s", item.GoodsID)
		}
	}

	// 新增
	if item.ID == "" {
		var InsertData models.MaActivity
		InsertData.Title = strings.TrimSpace(item.Title)
		InsertData.Color = strings.TrimSpace(item.Color)
		InsertData.CouponBatchID = item.CouponBatchID
		InsertData.Content = strings.TrimSpace(item.Content)
		InsertData.MerchantID = item.MerchantID
		var req system_admin.ConfirmFileReq
		req.FileUrl = item.ImagePath
		res, err1 := SystemAdminClient.ConfirmFile(ctx, &req)
		if err1 != nil && res.Code != 0 {
			logx.Error(ctx, "activity confirm file error", logx.Any("res", res), logx.Any("err", err1.Error()))
			return
		}
		InsertData.ImagePath = res.FileUrl
		err = db.Model(&models.MaActivity{}).Create(&InsertData).Error
		if err != nil {
			err = errorx.New(fmt.Sprintf("操作失败: %s", err.Error()), -1)
			return
		}
	} else { // 编辑
		var ActivityCount int64
		var ActivityInfo models.MaActivity
		db.Model(&models.MaActivity{}).
			Where("id = ? and deleted = 0", item.ID).
			Take(&ActivityInfo).
			Count(&ActivityCount)
		if ActivityCount == 0 {
			err = errorx.New("活动不存在", -1)
			return
		}
		if item.Status != 0 && item.Status != 1 {
			err = errorx.New("状态错误", -1)
			return
		}
		if ActivityInfo.ImagePath != item.ImagePath {
			var req system_admin.ConfirmFileReq
			req.FileUrl = item.ImagePath
			res, err1 := SystemAdminClient.ConfirmFile(ctx, &req)
			if err1 != nil && res.Code != 0 {
				logx.Error(ctx, "activity confirm file error", logx.Any("res", res), logx.Any("err", err1.Error()))
				err = errorx.New("保存图片失败", -1)
				return
			}
			item.ImagePath = res.FileUrl
		}
		//UpdateData := make(map[string]interface{})
		//UpdateData["title"] = strings.TrimSpace(item.Title)
		//UpdateData["image_path"] = strings.TrimSpace(item.ImagePath)
		//UpdateData["color"] = strings.TrimSpace(item.Color)
		//UpdateData["content"] = strings.TrimSpace(item.Content)
		//UpdateData["status"] = item.Status
		//db.Model(&models.MaActivity{}).
		//	Where("id = ?", item.ID).
		//	Updates(&UpdateData)

		err = dao.NewMaActivityRepo(ctx).UpdateColById(ctx, item,
			dal.MaActivity.Title, dal.MaActivity.ImagePath, dal.MaActivity.Color, dal.MaActivity.Content, dal.MaActivity.Status,
			dal.MaActivity.CouponBindType, dal.MaActivity.GoodsID, dal.MaActivity.GoodsClassID, dal.MaActivity.OnlineEventID,
			dal.MaActivity.CodeStartTime, dal.MaActivity.CodeEndTime, dal.MaActivity.PageStartTime, dal.MaActivity.PageEndTime,
			dal.MaActivity.TemplateName, dal.MaActivity.CodeBackgroundImg,
		)

		if err != nil {
			logx.Error(ctx, "MaActivityRepo.UpdateById", logx.Any("err", err))
			err = errorx.New(strings.Join([]string{"操作失败", err.Error()}, "\n"), -1)
			return err
		}

	}
	return
}

func (as ActivityService) Del(ctx context.Context, db *gorm.DB, MerchantID, ActivityID string) (err error) {
	var ActivityCount int64
	db.Model(&models.MaActivity{}).
		Where("id = ? and deleted = 0", ActivityID).
		Count(&ActivityCount)
	if ActivityCount == 0 {
		err = errorx.New("活动模板不存在", -1)
		return
	}

	db.Model(&models.MaActivity{}).
		Where("id = ?", ActivityID).
		UpdateColumn("deleted", 1)
	return
}

func (as ActivityService) Status(ctx context.Context, MerchantID, ID string, Status int64) (err error) {
	db := mysql.NewDB()
	var ActivityCount int64
	db.Model(&models.MaActivity{}).
		Where("id = ? and deleted = 0", ID).
		Count(&ActivityCount)
	if ActivityCount == 0 {
		err = errorx.New("活动模板不存在", -1)
		return
	}
	if Status != 0 && Status != 1 {
		err = errorx.New("状态错误", -1)
		return
	}
	db.Model(&models.MaActivity{}).
		Where("id = ?", ID).
		UpdateColumn("status", Status)
	return
}

// AddData 新增客户资料
func (as ActivityService) AddData(ctx context.Context, merchantID, phone, code, ActivityID, Name, Title, Content string) (redemptionCode string, err error) {
	db := mysql.NewDB()
	if code == "" {
		err = errorx.New("验证码不能为空", -1)
		return
	}
	// redis验证码校验
	boolean, err := helper.CheckSMSCode(redis.NewDB(), phone, code)
	if !boolean || err != nil {
		err = errorx.New("验证码校验错误", -1)
		return
	}

	// 活动用户信息校验
	var ActivityCount int64
	db.Model(&models.MaActivityData{}).
		Where("activity_id = ? and phone = ?", ActivityID, phone).
		Count(&ActivityCount)
	if ActivityCount > 0 {
		err = errorx.New("抱歉，用户信息已经存在", -1)
		return
	}

	var InsertData models.MaActivityData
	InsertData.ActivityID = ActivityID
	InsertData.Title = Title
	InsertData.Content = Content
	InsertData.Phone = phone
	InsertData.AddTime = time.Now()
	// 获取活动详情
	activityDetail, _ := dao.Activity{}.Detail(ctx, ActivityID)
	if activityDetail == nil {
		return "", errorx.New("活动不存在", -1)
	}
	// 旧的留资活动获码方式
	if activityDetail.CouponBatchID == "" {
		// 获取兑换码,ActivityID = 27时，不获取兑换码
		if ActivityID != "27" {
			expireTime := carbon.Now().AddDays(3).ToDateTimeString()
			codeList, err := redemption.RedemptionService{}.Add(ctx, db, "1", 1, 99, expireTime, Title)
			if err == nil && len(codeList) == 1 {
				InsertData.RedemptionCode = codeList[0]
			}
		} else {
			InsertData.RedemptionCode = ""
		}
	} else { // 新的获码方式
		expireTime := carbon.Now().AddDays(3).Carbon2Time().Unix() // 默认过期时间为3天
		codes, _ := coupon.CouponCode{}.GetCode(ctx, merchantID, activityDetail.CouponBatchID, 1, expireTime, "")
		if len(codes) > 0 {
			InsertData.RedemptionCode = codes[0]
		} else {
			return "", errorx.New("获取兑换码失败", -1)
		}
	}
	// 保存留资数据
	db.Model(&models.MaActivityData{}).Create(&InsertData)
	return InsertData.RedemptionCode, err
}

// ListData 客户资料
func (as ActivityService) ListData(ctx context.Context, merchantID string, activityID, phone, startTime, endTime string, page, limit int) (data interface{}, count int64, err error) {
	db := mysql.NewDB()

	if activityID == "" {
		err = errorx.New("活动id不能为空", -1)
		return
	}
	var res []struct {
		ID                     string                    `gorm:"column:id" json:"id"`
		Title                  string                    `gorm:"column:title" json:"title"`
		Content                string                    `gorm:"column:content" json:"-"`
		ContentJson            interface{}               `gorm:"-" json:"content"`
		Phone                  string                    `gorm:"column:phone" json:"phone"`
		AddTime                time.Time                 `gorm:"column:add_time" json:"-"`
		AddTimeFormated        string                    `gorm:"-" json:"add_time"`
		CountData              string                    `gorm:"column:count_data" json:"-"`
		CountDataFormated      []schema.OrderGoodsDetail `gorm:"-" json:"count_data"`
		RedemptionCode         string                    `gorm:"column:redemption_code" json:"redemption_code"`
		Value                  string                    `gorm:"column:value" json:"value"`
		SalesID                string                    `gorm:"column:sales_id" json:"sales_id"`
		RobotName              string                    `gorm:"column:robot_name" json:"robot_name"`
		GoodsID                string                    `gorm:"column:goods_id" json:"goods_id"`
		OutTradeNo             string                    `gorm:"column:out_trade_no" json:"out_trade_no"`
		UsageTime              time.Time                 `gorm:"column:usage_time" json:"-"`
		UsageTimeFormated      string                    `gorm:"-" json:"usage_time"`
		ExpirationTime         time.Time                 `gorm:"column:expiration_time" json:"-"`
		ExpirationTimeFormated string                    `gorm:"-" json:"expiration_time"`
		RedemptionState        string                    `gorm:"column:redemption_state" json:"redemption_state"`
		BrandName              string                    `gorm:"column:brand_name" json:"brand_name"`
		GoodsName1             string                    `gorm:"-" json:"goods_name1"`
	}

	field := "a.id, a.title, a.content, a.phone, a.add_time, o.count_data, " +
		"c.redemption_code, c.value, c.sales_id, c.robot_name, c.goods_id, c.out_trade_no, c.usage_time, c.expiration_time, c.redemption_state, c.brand_name"
	tx := db.Table(models.MaActivityData{}.TableName()+" as a").
		Joins("LEFT JOIN "+models.MaRedemptionCode{}.TableName()+" as c ON c.redemption_code = a.redemption_code").
		Joins("LEFT JOIN "+models.MaOrder{}.TableName()+" as o ON o.out_trade_no = c.out_trade_no").
		Where("a.activity_id = ?", activityID)
	if phone != "" {
		tx.Where("a.phone LIKE ?", "%"+phone+"%")
	}

	if startTime != "" && endTime != "" {
		tx.Where("a.add_time BETWEEN ? AND ?", startTime, endTime+" 23:59:59")
	}
	tx.Count(&count)

	helper.Gorm{}.Paginate(tx, page, limit).Order("a.id DESC").
		Select(field).
		Find(&res)

	for k, v := range res {
		if v.CountData != "" {
			CountData := common.Order{}.CountDataOldToNew(v.CountData)
			if len(CountData) > 0 {
				res[k].GoodsName1 = CountData[0].GoodsName
			}
			res[k].CountDataFormated = CountData
		}
		// 1. 转换兑换时间

		if !v.UsageTime.IsZero() {
			usageTimeBytes, _ := models.DateTime(v.UsageTime).MarshalDateTime()
			res[k].UsageTimeFormated = string(usageTimeBytes)
		}

		// 2. 转换生成时间
		addTimeBytes, _ := models.DateTime(v.AddTime).MarshalDateTime()
		res[k].AddTimeFormated = string(addTimeBytes)
		// 3. 转换过期时间
		ExpirationTimeBytes, _ := models.DateTime(v.ExpirationTime).MarshalDateTime()
		res[k].ExpirationTimeFormated = string(ExpirationTimeBytes)
		json.Unmarshal([]byte(v.Content), &res[k].ContentJson)
	}

	return res, count, db.Error
}

func (as ActivityService) VerifyMaActivityParam(item *models.MaActivity) (err error) {
	if item.CouponBindType != models.CouponBindTypeGoodsClass &&
		item.CouponBindType != models.CouponBindTypeGoods && item.CouponBindType != models.CouponBindTypeActivity {
		return errorx.New("优惠券绑定类型错误", -1)
	}

	if item.CouponBindType == models.CouponBindTypeGoodsClass && item.GoodsClassID == 0 {
		return errorx.New("商品标签不能为空", -1)
	}

	if item.CouponBindType == models.CouponBindTypeGoods && item.GoodsID == 0 {
		return errorx.New("商品id不能为空", -1)
	}

	if item.CouponBindType == models.CouponBindTypeActivity && item.OnlineEventID == 0 {
		return errorx.New("活动id不能为空", -1)
	}

	if item.CodeStartTime == 0 {
		return errorx.New("码开始时间不能为空", -1)
	}

	if item.CodeEndTime == 0 {
		return errorx.New("码结束时间不能为空", -1)
	}

	if item.PageStartTime == 0 {
		return errorx.New("页面开始时间不能为空", -1)
	}

	if item.PageEndTime == 0 {
		return errorx.New("页面结束时间不能为空", -1)
	}

	return nil
}
